﻿using SalesSys.DAL.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
//using hlib.Code;
using SalesSys.BLL.Depot;
using SalesSys.Comm.BLL;
using SalesSys.Comm.Utility;

namespace SalesSys.BLL.Sales
{
    public class OrderBLL : BaseBLL<Order, Guid>, IOrderBLL
    {
        /// <summary>
        /// 最小预付款标准
        /// </summary>
        public const  decimal payments = 0.8M;

        public const decimal advanceProportion = 0.8M;

       // public const decimal floating = 0.1;
        /// <summary>
        /// 设置订单状态
        /// </summary>
        /// <param name="createrId">修改人编号</param>
        /// <param name="guid">订单编号</param>
        /// <param name="orderState">订单状态</param>
        public void SetState(Guid createrId, Guid guid, OrderState orderState)
        {
            var empBll = new EmployeeBLL();
            var order = Rep.Find(guid);
            if (order == null)
                throw new NullReferenceException();
            order.State = orderState;
            SetOrderChangeRecord(order, DiscountType.StateChange, empBll.Details(createrId));
            Rep.Update(order);
        }
        
        /// <summary>
        /// 结算
        /// </summary>
        /// <param name="order"></param>
        /// <remarks>
        /// 重新计算订单金额
        /// 设置货款、运费
        /// 比较货款、运费，与实际支付差额
        /// 多出部分退回
        /// 设置订单状态：已结算
        /// 
        /// </remarks>
        public void Settlement(Order order, Employee emp = null)
        {
            using (var tran = new TransactionScope())
            {
                // 重新计算订单金额
                //order.CalcUnitDiscount();
                order.CalcNew();
                order.CalcDelivery();
                //设置订单状态：已结算
                if (!order.IsSettlement)
                {
                    order.SettlementTime = DateTime.Now;
                    order.IsSettlement = true;
                    order.State = OrderState.Settlement;
                }

                SetOrderChangeRecord(order, DiscountType.StateChange, null, 0, "订单提交结算");
                new FinanceBLL().OrderSettlementBalanceReturned(order, emp);
                Rep.Update(order);
                OrderBLL.AccountChangePayOrder(order.Account);
                tran.Complete();
            }
        }

        /// <summary>
        /// 取消订单
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="empId"></param>
        /// <remarks>
        /// 取消订单
        /// 记录到订单记录
        /// </remarks>
        public void Cancel(Guid orderId, Guid empId)
        {

            using (var tran = new TransactionScope())
            {
                EmployeeBLL employeeBLL = new EmployeeBLL();
                var emp = employeeBLL.Details(empId);
                var order = Rep.Find(orderId);
                if (order.State == OrderState.Cancel || order.State == OrderState.Return || order.State == OrderState.End)
                {
                    throw new ArgumentException("退款失败，错误的订单状态！");
                }
                //var old = Rep.Find(orderId);
                //old.State = OrderState.Cancel;
                if (emp != null)
                    SetOrderChangeRecord(order, DiscountType.Msg, emp, 0, "订单被[" + emp.Name + "]取消");

                //为避免退款之后 普通预付款重新支付
                order.State = OrderState.Cancel;
                var result = Rep.Update(order);
                //判断是否是锁价单转成的计划单，如果是，那么退款是直接退款到锁价单，否则，退款到余额
                if (order.LockOrder==null)
                {
                    OrderRefund(order, emp);
                }
                else//是锁价单转成的计划单，运费无论是公户还是私户，都是退款到个人账户
                {
                    if (order.PaidDelivery > 0)
                    {
                        var re2 = financeBll.OrderRefund(order.Id, order.DeliveryAccount, order.PaidDelivery, "取消计划单触发的运费退款操作");
                        if (re2)
                        {
                            SetOrderChangeRecord(order, DiscountType.Msg, emp, 0,
                                "订单被" + (emp != null ? "[" + emp.Name + "]" : "") + "取消,订单运费退款[" + order.PaidDelivery.ToString("F2") + "]");
                        }
                    }
                }
               

                var stockLockBll = new StockLockBLL();
                //核销锁库单
                stockLockBll.WriteOffSheet(order);
              
                //order = Rep.Find(orderId);
               
                //if (order.State == OrderState.Pending)
                //{
                //    var old = Rep.Find(orderId);
                //    old.State = OrderState.Cancel;
                //    SetOrderChangeRecord(old, DiscountType.Msg, emp, 0, "订单被取消");
                //    var result = Rep.Update(old);
                //}
                //else
                //{
                //    order.IsApproval = true;
                //    SetOrderChangeRecord(order, DiscountType.StateChange, emp, 0, "提交计划单取消审批");
                //    Rep.Update(order);
                //    //取消审批
                //    SequenceApprovalBLL.CancelOrderApproval cancelOrderBll = new SequenceApprovalBLL.CancelOrderApproval();
                //    cancelOrderBll.Submit(order);//取消审批
                //}
              tran.Complete();
            }
        }

        private static void OrderRefund(Order order, Employee emp)
        {
            FinanceBLL financeBll = new FinanceBLL();
            using (var tran = new TransactionScope())
            {
                if (order.Prepayments > 0)
                {
                    //退款  
                    var refundSuccess = financeBll.OrderRefund(order.Id, order.Account, order.Prepayments,
                        "取消计划单触发的退款操作");
                    if (refundSuccess)
                    {
                        order.Refund = order.Prepayments;
                        SetOrderChangeRecord(order, DiscountType.Msg, emp, 0, "订单被" + (emp != null ? "[" + emp.Name + "]" : "") + "取消,订单退款[" + order.Prepayments.ToString("F2") + "]");
                    }
                }
                if (order.PaidDelivery > 0)
                {
                    var re2 = financeBll.OrderRefund(order.Id, order.DeliveryAccount, order.PaidDelivery, "取消计划单触发的运费退款操作");
                    if (re2)
                    {
                        SetOrderChangeRecord(order, DiscountType.Msg, emp, 0,
                            "订单被" + (emp != null ? "[" + emp.Name + "]" : "") + "取消,订单运费退款[" + order.PaidDelivery.ToString("F2") + "]");
                    }
                }
                tran.Complete();
            }
        }

        /// <summary>
        /// 直发计划单创建
        /// </summary>
        /// <param name="order"></param>
        /// <remarks>
        /// 检查订单类型与供应商是否相符
        /// 设置订单信息
        /// 通过账户判断是否非标
        /// 判断商品是否归属供应商
        /// 计算商品价格：优惠、非标
        /// 计算总价、
        /// 设置运费户头，计算运费
        /// A.判断是否需要议价，提交审批流程，记录日志
        /// A.是否需要锁价，提交审批流程，记录日志
        /// A.无需审批，等待支付，信用客户处理，记录日志
        /// </remarks>
        public void DirectCreate(Order orderDto)
        {
            if (orderDto.Provider.ProviderType != ProviderType.Producer)
                throw new Exception("所选供应商信息不是钢厂");

            this.CreateOrder(orderDto);
        }

        /// <summary>
        /// 商品锁价单创建
        /// </summary>
        /// <param name="order"></param>
        ///<remarks>
        /// 获取对应锁价单
        /// 检查商品信息是否与锁价相同
        /// 计算金额
        /// 检查锁价单金额
        /// 扣除锁价单金额，计入已支付
        /// 记录日志
        /// </remarks>
        public void ProductLockCreate(Order order)
        {
            if (order.LockOrder == null)
                throw new Exception("该订单未找到相关联锁价单");

            if (!order.LockOrder.IsGoodsLock)
                throw new Exception("该锁价单不是商品锁价");

            //this.CreateOrder(order);
            CreateLockPriceOrder(order);

        }

        /// <summary>
        /// 基价锁价创建
        /// </summary>
        /// <param name="order"></param>
        ///<remarks>
        /// 获取对应锁价单
        /// 检查商品信息是否与锁价相同
        /// 计算金额
        /// 检查锁价单金额
        /// 扣除锁价单金额，计入已支付
        /// 记录日志
        /// </remarks>
        public void BasePriceLockCreate(Order order)
        {
            if (order.LockOrder == null)
                throw new Exception("该订单未找到相关联锁价单");

            if (order.LockOrder.IsGoodsLock)
                throw new Exception("该锁价单不是基价锁价");
            //this.CreateOrder(order);

            CreateLockPriceOrder(order);
        }

        /// <summary>
        /// 自采直销
        /// </summary>
        /// <param name="order"></param>
        /// <remarks>
        /// 
        /// </remarks>
        public void FreedomCreate(Order order)
        {
            if (order.Provider.ProviderType != ProviderType.Merchant)
                throw new Exception("所选供应商信息不是自采贸易商");
            this.CreateOrder(order);
        }

        /// <summary>
        /// 库提销售
        /// </summary>
        /// <param name="order"></param>
        public void DepotCreate(Order order)
        {
            if (order.Provider.ProviderType != ProviderType.Depot)
                throw new Exception("所选供应商信息不是仓库");
            this.CreateOrder(order);
        }

        /// <summary>
        /// 检查库存，不足返回不足项
        /// </summary>
        /// <param name="providerId"></param>
        /// <param name="infos"></param>
        /// <returns></returns>
        public CommodityInfo ChackDepotStock(Guid providerId,IEnumerable<CommodityInfo> infos)
        {
            var dcmmdBll = new DepotCommodityBLL();
            var ids = infos.Select(p => p.Commodity.Id).ToArray();
            var dcommoditys = dcmmdBll.GetList(p => p.ProviderId == providerId && ids.Contains(p.CommodityId)).ToArray();
            foreach (var info in infos)
            {
               var re= dcommoditys.Any(p => p.CommodityId == info.Commodity.Id && p.Amount >= info.Weight);
                if (!re)
                {
                    return info;
                }
            }
            return null;
        }

        /// <summary>
        /// 锁价单创建计划单
        /// </summary>
        /// <remarks>
        /// 查询价格，判断库存
        ///计算总价
        ///查看锁价单剩余金额是否足够
        ///添加已扣金额-->锁价单中金额
        ///创建计划单,设置支付金额
        /// </remarks>
        private void CreateLockPriceOrder(Order order)
        {    
            if (order.CommodityInfos.Count == 0)
                    throw new Exception("商品数量不能为0");
         var comds=   ChackDepotStock(order.Provider.Id,order.CommodityInfos);
            if (comds!=null)
            {
                throw new ArgumentException("库存不足");
            }               
            var infoList = SelectRecordsCommodityInfos(order);
                order.CommodityInfos = infoList;
            using (var tran = new TransactionScope())
            {
               // order.OrderType = order.LockOrder.OrderType;
                order.Customer = order.LockOrder.Customer;
                order.Provider = order.LockOrder.Provider;
                order.Account = order.LockOrder.Account;
                order.IsStandard = order.LockOrder.IsStandard;
                order.LockOrder = order.LockOrder;
                order.ApplyDiscount = order.LockOrder.ApplyDiscount;
                //order.UnitDiscount = order.LockOrder.UnitDiscount; CalcUnitDiscount方法会根据供应商非标、先款进行优惠汇总
                order.IsLockPrice = true;
                //
                order.IsFullPayment = true;
                order.Records = new List<OrderRecord>();
                order.Records.Add(new OrderRecord()
                {
                    CreateTime = DateTime.Now,
                    DiscountType = DiscountType.Msg,
                    Remarks = "订单创建"
                });
                //其他信息
                order.CreateTime = DateTime.Now;
                order.SendTime = DateTime.Now;
                order.CalcUnitDiscount();
                order.CalcNew(); //计算商品总价及总重
                order.CalcDelivery(); //计算运费合计

                AccountBLL accountBLL = new AccountBLL();
                //运费户头
                if (order.IsPublicDelivery)
                    order.DeliveryAccount = order.Account;
                else
                    order.DeliveryAccount = accountBLL.GetCashAccountByCustomerId(order.Customer.Id);

                order.State = OrderState.Pending;
                //
               // var total = order.LockOrder.GetTotal();//锁价单总价上浮10%
                var surplus = order.LockOrder.GetSurplus();
                if (surplus < order.Total)
                {
                    throw new ArgumentException("超出锁价金额");
                }
                //
                order.Prepayments = order.Total;
                 
                order.IsApproval = order.ApplyDiscount > 0 || order.IsLockPrice;
                //申请单价大于0则提交议价审批，否则判断是否需要锁价审批  
                if (order.ApplyDiscount > 0)
                {
                    order.ProcessState = ProcessState.Bargaining;
                    if (order.Provider.Manager != null)
                        OrderBLL.SetOrderChangeRecord(order, DiscountType.Msg, null, 0, "等待[" + order.Provider.Manager.Name + "]议价审批");
                    Rep.Insert(order);
                    //提交议价审批流程
                    SequenceApprovalBLL.BargainingApproval approvalBll = new SequenceApprovalBLL.BargainingApproval();
                    approvalBll.Submit(order, order.ApplyDiscount);
                }
                else if (order.IsLockPrice)
                {
                    order.ProcessState = ProcessState.LockPrice;
                    if (order.Provider.Manager != null)
                        OrderBLL.SetOrderChangeRecord(order, DiscountType.Msg, null, 0, "等待[" + order.Provider.Manager.Name + "]锁价审批");
                    Rep.Insert(order);
                    SequenceApprovalBLL.LockPriceApproval approvalBll = new SequenceApprovalBLL.LockPriceApproval();
                    approvalBll.Submit(order); //锁价审批
                }
                else
                {
                    order.ProcessState = ProcessState.FullPayment;
                    OrderBLL.SetOrderChangeRecord(order, DiscountType.StateChange, null, 0, "订单待付款确认");
                    Rep.Insert(order);
                    //this.PaymentOrder(order);
                }
                var stockLockBll = new StockLockBLL();
                //贸易商不用创建锁库单
                //if (order.Provider.ProviderType != ProviderType.Merchant)
                //{
                    //创建锁库单
                    stockLockBll.CreateByOrder(order);
                //}
                tran.Complete();
            }
        }

        private static List<CommodityInfo> SelectRecordsCommodityInfos(Order order)
        {
            var infoList = new List<CommodityInfo>();
            var ids = order.CommodityInfos.Select(p => p.Commodity.Id).ToArray();
            var records = order.LockOrder.DepotCommodityRecords.Where(p =>p.Provider.Id==order.Provider.Id&& ids.Contains(p.CommodityId)).ToArray();
            foreach (var item in order.CommodityInfos)
            {
                var commodityInfo = new CommodityInfo();
                //找到锁价单商品历史 todo..
                var record =records.FirstOrDefault(
                        p => p.Provider.Id == order.Provider.Id && p.Commodity.Id == item.Commodity.Id);
                if (record == null)
                    throw new Exception("锁价单转计划单不得选择锁价单锁价以外的商品");
                //查询对应仓库商品当前状态
                //var tmpInfo = dcmmdBll.GetDepotCommodity(order.Provider.Id, item.Commodity.Id);
                //if (tmpInfo == null)
                //    throw new Exception("选择商品与供应商不符");
                //if (tmpInfo.CheckAmount(item.Weight))
                //    throw new Exception("商品数量不允许超过库存数量");
                //强制设置价格为历史价格
                commodityInfo.Price = record.Price;
                commodityInfo.Commodity = record.Commodity;
                commodityInfo.Weight = item.Weight;
                commodityInfo.Count = item.Count;
                commodityInfo.CalcNew();
                infoList.Add(commodityInfo);
            }
            return infoList;
        }

        /// <summary>
        /// 创建
        /// </summary>
        /// <param name="order"></param>
        private void CreateOrder(Order order)
        {
            using (var tranOrder = new TransactionScope())
            {
                //判断是否是锁价单
                if (order.LockOrder == null)
                {
                    #region 商品列表
                    //验证商品数量不能为0，并判断商品数量不允许超过库存数量
                    if (order.CommodityInfos.Count == 0)
                    {
                        throw new Exception("商品数量不能为0");
                    }
                    var dcmmdBll = new DepotCommodityBLL();
                    //贸易商不用验证商品类型及库存数量
                    if (order.Provider.ProviderType != ProviderType.Merchant)
                    {
                        foreach (var item in order.CommodityInfos)
                        {
                            var tmpInfo = dcmmdBll.GetDepotCommodity(order.Provider.Id, item.Commodity.Id);
                            if (tmpInfo == null)
                                throw new Exception("选择商品与供应商不符");
                            if (!tmpInfo.CheckAmount(item.Weight))
                                throw new Exception("商品数量不允许超过库存数量");
                        }
                    }
                    #endregion
                    order.IsStandard = !order.Account.IsCash;
                }
                else
                {
                    #region 商品列表
                    //判断是商品锁价还是锁基价
                    if (order.CommodityInfos.Count == 0)
                        throw new Exception("商品数量不能为0");

                    var dcmmdBll = new DepotCommodityBLL();
                    var infoList = new List<CommodityInfo>();
                    foreach (var item in order.CommodityInfos)
                    {
                        var commodityInfo = new CommodityInfo();
                        //找到锁价单商品历史 todo..
                        var record = order.LockOrder.DepotCommodityRecords.FirstOrDefault(p => p.Provider.Id == order.Provider.Id && p.Commodity.Id == item.Commodity.Id);
                        if (record == null)
                            throw new Exception("锁价单转计划单不得选择锁价单锁价以外的商品");
                        //查询对应仓库商品当前状态
                        //var tmpInfo = dcmmdBll.GetDepotCommodity(order.Provider.Id, item.Commodity.Id);
                        //if (tmpInfo == null)
                        //    throw new Exception("选择商品与供应商不符");
                        //if (tmpInfo.CheckAmount(item.Weight))
                        //    throw new Exception("商品数量不允许超过库存数量");
                        //强制设置价格为历史价格
                        commodityInfo.Price = record.Price;
                        commodityInfo.Commodity = record.Commodity;
                        commodityInfo.Weight = item.Weight;
                        commodityInfo.Count = item.Count;
                        commodityInfo.CalcNew();
                        infoList.Add(commodityInfo);
                    }
                    order.CommodityInfos = infoList;
                    #endregion
                    order.OrderType = order.LockOrder.OrderType;
                    order.Customer = order.LockOrder.Customer;
                    order.Provider = order.LockOrder.Provider;
                    order.Account = order.LockOrder.Account;
                    order.IsStandard = order.LockOrder.IsStandard;
                    order.LockOrder = order.LockOrder;
                    order.ApplyDiscount = order.LockOrder.ApplyDiscount;
                    order.UnitDiscount = order.LockOrder.UnitDiscount;
                }
                // order.IsFullPayment = true;
                order.Records = new List<OrderRecord>();
                order.Records.Add(new OrderRecord() { CreateTime = DateTime.Now, DiscountType = DiscountType.Msg, Remarks = "订单创建" });
                //其他信息
                order.CreateTime = DateTime.Now;
                order.SendTime = DateTime.Now;
                order.CalcUnitDiscount();
                order.CalcNew();//计算商品总价及总重
                order.CalcDelivery();//计算运费合计

                AccountBLL accountBLL = new AccountBLL();
                //运费户头
                if (order.IsPublicDelivery)
                    order.DeliveryAccount = order.Account;
                else
                    order.DeliveryAccount = accountBLL.GetCashAccountByCustomerId(order.Customer.Id);

                order.State = OrderState.Pending;
                order.IsApproval = order.ApplyDiscount > 0 || order.IsLockPrice;
                //申请单价大于0则提交议价审批，否则判断是否需要锁价审批  
                if (order.ApplyDiscount > 0)
                {
                    order.ProcessState = ProcessState.Bargaining;
                    if (order.Provider.Manager != null)
                        OrderBLL.SetOrderChangeRecord(order, DiscountType.Msg, null, 0, "等待[" + order.Provider.Manager.Name + "]议价审批");
                    Rep.Insert(order);
                    //提交议价审批流程
                    SequenceApprovalBLL.BargainingApproval approvalBll = new SequenceApprovalBLL.BargainingApproval();
                    approvalBll.Submit(order, order.ApplyDiscount);
                }
                else if (order.IsLockPrice)
                {
                    order.ProcessState = ProcessState.LockPrice;
                    if (order.Provider.Manager != null)
                        OrderBLL.SetOrderChangeRecord(order, DiscountType.Msg, null, 0, "等待[" + order.Provider.Manager.Name + "]锁价审批");
                    Rep.Insert(order);
                    SequenceApprovalBLL.LockPriceApproval approvalBll = new SequenceApprovalBLL.LockPriceApproval();
                    approvalBll.Submit(order);//锁价审批
                }
                else
                {
                    if (order.Provider.Manager == null || order.Provider.MainFieldMan == null)
                        throw new Exception("供应商驻厂专员或区域经理未配置，请联系管理员。");
                    order.ProcessState = ProcessState.FullPayment;
                    OrderBLL.SetOrderChangeRecord(order, DiscountType.StateChange, null, 0, "订单待付款确认");
                    Rep.Insert(order);
                    this.PaymentOrder(order);
                }
                var stockLockBll = new StockLockBLL();
                //贸易商不用创建锁库单
                //if (order.Provider.ProviderType != ProviderType.Merchant)
                //{
                    //创建锁库单
                    stockLockBll.CreateByOrder(order);
                //}
                tranOrder.Complete();
            }
        }


        /// <summary>
        /// 添加订单修改日志
        /// </summary>
        /// <param name="order"></param>
        /// <param name="discountType"></param>
        /// <param name="handler"></param>
        /// <param name="price"></param>
        /// <param name="msg"></param>
        public static void SetOrderChangeRecord(Order order, DiscountType discountType, IEmployee handler, decimal price = 0, string msg = null, string remark = null)
        {
           
            Order newOrder = order;
            string linkId = handler == null ? "" : handler.Id.ToString();
            if (newOrder.Records == null)
            {
                newOrder.Records = new List<OrderRecord>();
            }
            if (msg != null)
            {
                if (handler != null)
                    newOrder.Records.Add(new OrderRecord() { CreateTime = DateTime.Now, DiscountType = DiscountType.Msg, LinkId = linkId, Remarks = handler.Name + " : " + msg, Price = price });
                else
                    newOrder.Records.Add(new OrderRecord() { CreateTime = DateTime.Now, DiscountType = DiscountType.Msg, LinkId = linkId, Remarks = msg, Price = price });
                return;
            }
            string handlerId = null;
            string handlerName = null;
            if (handler != null)
            {
                handlerId = "" + handler.Id;
                handlerName = ",处理人:" + handler.Name;
            }
            switch (discountType)
            {
                case DiscountType.Msg:
                    newOrder.Records.Add(new OrderRecord() { DiscountType = DiscountType.Msg, LinkId = linkId, Remarks = handlerName + " 订单改变:" + newOrder.State.GetDescInfo() });
                    break;
                case DiscountType.Payment:
                    newOrder.Records.Add(new OrderRecord() { DiscountType = DiscountType.Payment, LinkId = linkId, Remarks = "先款优惠:" + price });
                    break;
                case DiscountType.Nonstandard:
                    newOrder.Records.Add(new OrderRecord() { DiscountType = DiscountType.Nonstandard, LinkId = linkId, Remarks = "非标优惠:" + price });
                    break;
                case DiscountType.PriceChange:
                    newOrder.Records.Add(new OrderRecord() { DiscountType = DiscountType.PriceChange, LinkId = linkId, Remarks = "价格变化:" + price + handlerName, Tag = handlerId });
                    break;
                case DiscountType.WeightChange:
                    newOrder.Records.Add(new OrderRecord() { DiscountType = DiscountType.PriceChange, LinkId = linkId, Remarks = "重量变化:" + price + handlerName, Tag = handlerId });
                    break;
                case DiscountType.Approval:
                    newOrder.Records.Add(new OrderRecord() { DiscountType = DiscountType.Approval, LinkId = linkId, Remarks = "审批优惠:" + price });
                    break;
                case DiscountType.StateChange:
                    newOrder.Records.Add(new OrderRecord() { DiscountType = DiscountType.StateChange, LinkId = linkId, Remarks = "状态变化:" + order.State.GetDescInfo(), Tag = ((int)order.State).ToString() });
                    break;
                case DiscountType.BaseInfo:
                    newOrder.Records.Add(new OrderRecord() { DiscountType = DiscountType.BaseInfo, LinkId = linkId, Remarks = "基本信息修改" + remark + ",修改人：" + handler.Name, Tag = "" + handler.Id });
                    break;
                default:
                    throw new ArgumentOutOfRangeException("discountType");
            }

        }

        private bool AllowToFactory(Order order)
        {
            var payPass = order.Prepayments >= order.Total * payments;
            return payPass || order.Customer.CreditGrade() || financeBll.BalanceSum(order.Customer.Id,order.Creater.Id) >= (order.Total - order.Prepayments) * payments;

        }
        
        FinanceBLL financeBll = new FinanceBLL();
        /// <summary>
        /// 支付方法
        /// </summary>
        /// <param name="order"></param>
        private void PaymentOrder(Order order)
        {
            if (order.State == OrderState.Cancel)
            {
                throw new ArgumentException("计划单已取消，无法支付");
            }
         
            var payment =order.IsSettlement? financeBll.PaymentOrder(order):financeBll.PaymentOrder2(order,null,advanceProportion); //扣款
            if (payment > 0)
                OrderBLL.SetOrderChangeRecord(order, DiscountType.Msg, null, payment, "订单支付:[" + payment.ToString("C")+ "]元");
            order.Prepayments += payment;
            var paidDelivery = financeBll.PaymentOrderDelivery(order);
            if (paidDelivery > 0)
                OrderBLL.SetOrderChangeRecord(order, DiscountType.Msg, null, paidDelivery, "订单运费支付:[" + paidDelivery.ToString("C") + "]元");
            order.PaidDelivery += paidDelivery;
            //是否信誉客户
            if (AllowToFactory(order))
            {
               
                if (order.ProcessState == ProcessState.FullPayment)
                {
                     order.ProcessState = ProcessState.Checked;
                }
                if (order.IsSettlement)
                {
                    if (order.DeliveryPriceTotal > order.PaidDelivery)
                    {
                        order.PaidDelivery += financeBll.PaymentOrderDelivery(order);
                    }
                    this.Edit(order);
                }
                else if (order.State == OrderState.Pending && order.ProcessState == ProcessState.Checked)
                {
                    //通知驻场接单
                    this.SendDockingOrder(order);
                    string mainFieldMan;
                    //库提计划单运营发货，驻厂计划单驻厂发货，贸易商计划单采购发货
                    if (order.Provider.ProviderType == ProviderType.Depot)
                    {
                        mainFieldMan = order.Provider.OperationsMan != null ? "运营[" + order.Provider.OperationsMan.Name + "]" : "";
                    }
                    else
                    {
                        mainFieldMan = order.Provider.MainFieldMan != null ? "驻厂[" + order.Provider.MainFieldMan.Name + "]" : "";
                    }

                    if (order.Prepayments >= (Math.Round(order.Total * payments*100)*Convert.ToDecimal(0.01)))
                    {
                        OrderBLL.SetOrderChangeRecord(order, DiscountType.Msg, null, payment, "订单款项符合支付要求,通知" + mainFieldMan + "接单");
                    }
                    else if (order.Customer.CreditGrade())
                    {
                        OrderBLL.SetOrderChangeRecord(order, DiscountType.Msg, null, payment, "订单客户信用达标,通知" + mainFieldMan + "接单");
                    }
                    else if (financeBll.BalanceSum(order.Customer.Id,order.Creater.Id) >= (order.Total - order.Prepayments) * payments)
                    {
                        OrderBLL.SetOrderChangeRecord(order, DiscountType.Msg, null, payment, "订单客户的总账户余额，大于当前订单剩余待支付金额，通知" + mainFieldMan + "接单");
                    }
                }
            }
                this.Edit(order);

        }

    

        /// <summary>
        /// 通知驻场接单
        /// </summary>
        /// <param name="order"></param>
        private void SendDockingOrder(Order order)
        {
            var old = Rep.Find(order.Id);
            order.IsApproval = false;
            order.State = OrderState.Checked;
            Rep.Update(order);
            var nb = new NoticeInfoBLL();
            var str = string.Format("{0:M/d HH:mm} 客户经理[{1}] 新增计划单,编号为[{2}]", old.CreateTime, old.Creater.Name, old.CodeNum);
            //仓库由运营来处理订单，钢厂由驻厂，贸易商由采购
            if (order.Provider.ProviderType == ProviderType.Depot)
            {
                //通知运营订单变化
                if (old.Provider.OperationsMan != null)
                    nb.SendMsg(str, old.Provider.OperationsMan.Id, null);
            }
            else
            {
                //通知驻厂订单变化
                if (old.Provider.MainFieldMan != null)
                    nb.SendMsg(str, old.Provider.MainFieldMan.Id, null);
            }
        }

        /// <summary>
        /// 通知财务先款审核
        /// </summary>
        /// <param name="order"></param>
        private void SendFullPayment(Order order)
        {
            var old = Rep.Find(order.Id);
            order.ProcessState = ProcessState.FullPayment;
            Rep.Update(order);
        }

        static OrderBLL()
        {
            //增加账户变化时间
            FinanceBLL.AccountBalanceChange = AccountChangePayOrderNew;
            SequenceApprovalBLL.BargainingApproval.ApprovalEndHandle += BargainingApproval_ApprovalEndHandle;
            SequenceApprovalBLL.LockPriceApproval.ApprovalEndHandle += LockPriceApproval_ApprovalEndHandle;
            SequenceApprovalBLL.CancelOrderApproval.ApprovalEndHandle += CancelOrderApproval_ApprovalEndHandle;
            SequenceApprovalBLL.OrderReturnApproval.ApprovalEndHandle += OrderReturnApproval_ApprovalEndHandle;
        }

        /// <summary>
        /// 监听财务变化，支付订单
        /// </summary>
        /// <param name="account"></param>
        public static void AccountChangePayOrder(Account account)
        {
            FinanceBLL financeBll = new FinanceBLL();
            OrderBLL orderBll = new OrderBLL();
            AccountBLL accountBll = new AccountBLL();
            var accountList = accountBll.GetListByCustomerId(account.Customer.Id);
            var idsList = accountList.Select(p => p.Id).ToList();

            //查询该户头下所有订单，按照顺序进行付款1、已结算\时间排序 2、查询锁价单 3、普通预付款
            var orderList = orderBll.GetList(p => idsList.Contains(p.Account.Id) && p.IsSettlement == true && (p.Total > p.Prepayments || p.DeliveryPriceTotal > p.PaidDelivery)).OrderByDescending(p => p.CreateTime);
            foreach (var order in orderList)
            {
                if (order.Total > order.Prepayments)
                    orderBll.PaymentOrder(order);
            }

            //查询锁价单
            LockOrderBLL.AccountChangePayLockOrder(account);

            //普通预付款
            //orderList = orderBll.GetList(p => idsList.Contains(p.Account.Id) && p.ProcessState == ProcessState.FullPayment && p.State == OrderState.Pending).OrderByDescending(p => p.CreateTime);
            orderList = orderBll.GetList(p => idsList.Contains(p.Account.Id) && p.State != OrderState.Cancel && p.State != OrderState.End && p.State != OrderState.Refund && p.State != OrderState.Return).OrderBy(p => p.CreateTime);
            
            foreach (var order in orderList)
            {
                orderBll.PaymentOrder(order);
            }
        }

        public static void AccountChangePayOrderNew(Account account, Guid empId, Guid customerId)
        {
            FinanceBLL financeBll = new FinanceBLL();
            OrderBLL orderBll = new OrderBLL();
            AccountBLL accountBll = new AccountBLL();
            //ar accountList = accountBll.GetListByCustomerId(account.Customer.Id);
            //var idsList = accountList.Select(p => p.Id).ToList();

            //查询该户头下所有订单，按照顺序进行付款1、已结算\时间排序 2、查询锁价单 3、普通预付款
            var orderList = orderBll.GetList(p =>p.Creater.Id==empId&&p.Customer.Id==customerId&&p.Account.Id==account.Id && p.IsSettlement == true && (p.Total > p.Prepayments || p.DeliveryPriceTotal > p.PaidDelivery)).OrderByDescending(p => p.CreateTime);
            foreach (var order in orderList)
            {
                if (order.Total > order.Prepayments)
                    orderBll.PaymentOrder(order);
            }

            //查询锁价单
            LockOrderBLL.AccountChangePayLockOrderNew(account,empId,customerId);

            //普通预付款
            //orderList = orderBll.GetList(p => idsList.Contains(p.Account.Id) && p.ProcessState == ProcessState.FullPayment && p.State == OrderState.Pending).OrderByDescending(p => p.CreateTime);
            orderList = orderBll.GetList(p =>p.Creater.Id==empId&&p.Customer.Id==customerId&&p.Account.Id==account.Id && p.State != OrderState.Cancel && p.State != OrderState.End && p.State != OrderState.Refund && p.State != OrderState.Return).OrderBy(p => p.CreateTime);

            foreach (var order in orderList)
            {
                orderBll.PaymentOrder(order);
            }
        }
        /// <summary>
        /// 议价审批处理方法
        /// </summary>
        /// <param name="id"></param>
        /// <param name="success"></param>
        /// <param name="price"></param>
        private static void BargainingApproval_ApprovalEndHandle(Guid id, bool success, decimal price, string msg)
        {
            OrderBLL bll = new OrderBLL();
            var order = bll.Details(id);
            if (success)
            {
                OrderBLL.SetOrderChangeRecord(order, DiscountType.Msg, null, price, "审批通过：议价金额" + price);
                bll.Edit(order);
                if (order.IsLockPrice)
                {
                    if (order.Provider.Manager != null)
                        OrderBLL.SetOrderChangeRecord(order, DiscountType.Msg, null, 0, "等待[" + order.Provider.Manager.Name + "]锁价审批");
                    order.ProcessState = ProcessState.LockPrice;
                    SequenceApprovalBLL.LockPriceApproval approvalBll = new SequenceApprovalBLL.LockPriceApproval();
                    approvalBll.Submit(order);//锁价审批
                }
                else
                {
                    if (order.State == OrderState.Cancel)
                    {
                        return;
                    }
                    bll.SendFullPayment(order);
                    bll.PaymentOrder(order);
                }
            }
            else
            {
                order.Records.Add(new OrderRecord() { CreateTime = DateTime.Now, DiscountType = DiscountType.Msg, Remarks = "议价审批驳回" });
                bll.Edit(order);
                bll.Cancel(id, Guid.Empty);
            }
        }

        /// <summary>
        /// 锁价审批处理方法
        /// </summary>
        /// <param name="id"></param>
        /// <param name="success"></param>
        private static void LockPriceApproval_ApprovalEndHandle(Guid id, bool success, string msg)
        {
            OrderBLL bll = new OrderBLL();
            var order = bll.Details(id);
            //提交财务先款审核
            bll.SendFullPayment(order);
            if (success)
            {
                order.Records.Add(new OrderRecord() { CreateTime = DateTime.Now, DiscountType = DiscountType.Msg, Remarks = "锁价审批通过" });
                if (order.State == OrderState.Cancel)
                {
                    return;
                }
                bll.PaymentOrder(order);
            }
            else
            {
                order.Records.Add(new OrderRecord() { CreateTime = DateTime.Now, DiscountType = DiscountType.Msg, Remarks = "锁价审批驳回" });
                bll.Edit(order);
                bll.Cancel(id, Guid.Empty);
            }
        }

        /// <summary>
        /// 取消计划单回调事件
        /// </summary>
        /// <param name="id">计划单编号</param>
        /// <param name="success">审核状态</param>
        private static void CancelOrderApproval_ApprovalEndHandle(Guid id, bool success, string msg)
        {
            OrderBLL bll = new OrderBLL();
            var order = bll.Details(id);
            order.IsApproval = false;
            if (success)
            {
                //if (order.Prepayments >0)
                //{
                //    //退款  
                //    FinanceBLL financeBll = new FinanceBLL();

                //    var refundSuccess = financeBll.OrderRefund(order, order.Prepayments, "取消计划单触发的退款操作");
                //    if (refundSuccess)
                //    {
                //        order.Refund = order.Prepayments;
                //    }
                //}

                bll.Cancel(id, Guid.Empty);//提交取消申请时已记录是谁提交的取消申请
                order.Records.Add(new OrderRecord { CreateTime = DateTime.Now, DiscountType = DiscountType.Msg, Remarks = "计划单[取消]操作审核结果：[成功]" });
            }
            else
            {
                order.Records.Add(new OrderRecord { CreateTime = DateTime.Now, DiscountType = DiscountType.Msg, Remarks = "计划单[取消]操作审核结果：[驳回]" });
            }
            bll.Edit(order);
        }

        /// <summary>
        /// 计划单退货回调事件，
        /// </summary>
        /// <param name="id">计划单编号</param>
        /// <param name="success">审核状态</param>
        private static void OrderReturnApproval_ApprovalEndHandle(Guid id, bool success, string msg)
        {
            OrderBLL bll = new OrderBLL();
            var order = bll.Details(id);
            order.IsApproval = false;
            if (success)
            {
                FinanceBLL financeBll = new FinanceBLL();
               // var refundSuccess = financeBll.OrderRefund(order.Id,order.Account, order.Prepayments, "计划单退货触发的退款操作");

                OrderRefund(order,order.Creater);
                //if (refundSuccess)
                //{
                //    order.State = OrderState.Refund;
                //}
                //else
                //{
                //    order.State = OrderState.Return;
                //}


                order.Records.Add(new OrderRecord { CreateTime = DateTime.Now, DiscountType = DiscountType.Msg, Remarks = "计划单[退货]操作审核结果：[成功],款项已退" });
            }
            else
            {
                order.Records.Add(new OrderRecord { CreateTime = DateTime.Now, DiscountType = DiscountType.Msg, Remarks = "计划单[退货]操作审核结果：[失败]" });
            }
            bll.Edit(order);
        }

        /// <summary>
        /// 通过销售单创建出库单，并出库
        /// </summary>
        /// <param name="order"></param>
        public void ToDepotDelivery(Order order, Guid empId)
        {
            IDepotBLL bll = new DepotBLL();
            var empBll = new EmployeeBLL();
            var deliveryList = new DeliveryList();
            deliveryList.Creater = empBll.Details(empId);
            deliveryList.Provider = order.Provider;
            deliveryList.From = DeliveryListSource.Sale;
            deliveryList.FromId = order.Id;
            deliveryList.StockGoods = new List<StockGoods>();
            foreach (var info in order.CommodityInfos)
            {
                var goods = new StockGoods();
                goods.Commodity = info.Commodity;
                goods.Price = info.Price;
                goods.SourcePrice = info.SourcePrice;
                goods.Count = info.Count;
                goods.IsIn = false;
                goods.TotalWeight = info.Weight;
                deliveryList.StockGoods.Add(goods);
            }

            IBaseBLL<DeliveryList, Guid> deliveryListBll = new BaseBLL<DeliveryList, Guid>();

            using (var tran = new TransactionScope())
            {
                deliveryListBll.Create(deliveryList);
                order.IsToDeliveryList = true;

                bll.Delivery(deliveryList, true);
                Edit(order);
                tran.Complete();
            }

        }

        /// <summary>
        /// 修改商品信息后，所对应的商品库存需要做相应的调整
        /// </summary>
        /// <param name="order"></param>
        public void CommodityInfoWeightEdit(Order order, Order orderDto, IEmployee emp)
        {
            IDepotBLL bll = new DepotBLL();
            var empBll = new EmployeeBLL();
            var deliveryList = new DeliveryList();
            deliveryList.Creater = empBll.Details(emp.Id);
            deliveryList.Provider = order.Provider;
            deliveryList.From = DeliveryListSource.Sale;
            deliveryList.FromId = order.Id;
            deliveryList.StockGoods = new List<StockGoods>();
            foreach (var info in orderDto.CommodityInfos)
            {
                var eny = order.CommodityInfos.FirstOrDefault(p => p.Id == info.Id);
                if (eny.Weight != info.Weight)
                {
                    var goods = new StockGoods();
                    goods.Commodity = info.Commodity;
                    goods.Price = info.Price;
                    goods.SourcePrice = info.SourcePrice;
                    goods.Count = eny.Count > info.Count ? eny.Count - info.Count : info.Count - eny.Count;
                    goods.IsIn = eny.Weight > info.Weight;
                    goods.TotalWeight = eny.Weight > info.Weight ? eny.Weight - info.Weight : info.Weight - eny.Weight;
                    deliveryList.StockGoods.Add(goods);
                }
            }

            IBaseBLL<DeliveryList, Guid> deliveryListBll = new BaseBLL<DeliveryList, Guid>();

            deliveryListBll.Create(deliveryList);
            order.IsToDeliveryList = true;
            bll.Delivery(deliveryList, true);
        }

        /// <summary>
        /// 修改商品信息
        /// </summary>
        /// <param name="orderDto"></param>
        /// <param name="emp"></param>
        public void CommodityInfoEdit(Order orderDto, IEmployee emp)
        {
            var cmmdInfoDtos = orderDto.CommodityInfos;

            var msgList = new List<string>();

            var commBll = BllFactory.GetBll<BaseBLL<Commodity, Guid>>();
            var order = Details(orderDto.Id);
            foreach (var cmmdInfoDto in cmmdInfoDtos)
            {

                var eny = order.CommodityInfos.FirstOrDefault(p => p.Id == cmmdInfoDto.Id);
                // ciBll.Details(cmmdInfoDto.Id);
                if (eny == null)
                {
                    var newInfo = new CommodityInfo();
                    newInfo.Commodity = commBll.Details(cmmdInfoDto.Commodity.Id);
                    newInfo.Weight = cmmdInfoDto.Weight;
                    newInfo.Price = cmmdInfoDto.Price;
                    order.CommodityInfos.Add(newInfo);
                    msgList.Add(string.Format("添加商品:{0},￥{1} * {2}t", newInfo.Commodity.FillName(), newInfo.Price,
                        newInfo.Weight));
                }
                else if (cmmdInfoDto.Weight <= 0)
                {
                    order.CommodityInfos.Remove(eny);
                    msgList.Add("移除商品:" + cmmdInfoDto.Commodity.FillName());
                }
                else
                {
                    eny.Count = cmmdInfoDto.Count;
                    eny.Price = cmmdInfoDto.Price;
                    eny.Weight = cmmdInfoDto.Weight;
                }
            }
            var oldTotal = order.Total;
            order.CalcNew();
            var oldDelivery = order.DeliveryPriceTotal;
            order.DeliveryPrice = orderDto.DeliveryPrice;
            order.CalcDelivery();
            if (order.IsSettlement)
            {
                var employeeBll = new EmployeeBLL();
                var handler = employeeBll.Details(emp.Id);
                //order.Total, order.Total - oldTotal
                Settlement(order, handler);
            }
            if (oldTotal != order.Total)
            {
                msgList.Add("总货款变化：原:" + oldTotal.ToString("F2") + ",新:" + order.Total.ToString("F2"));
            }
            if (oldDelivery != order.DeliveryPriceTotal)
            {
                msgList.Add("总运费变化：原:" + oldDelivery.ToString("F2") + ",新:" + order.DeliveryPriceTotal.ToString("F2"));
            }
            using (var tran = new TransactionScope())
            {
                if (msgList.Count > 0)
                {
                    OrderBLL.SetOrderChangeRecord(order, DiscountType.PriceChange, emp, 0,
                        string.Join(";", msgList.ToArray()));
                }
                if (order.State == OrderState.Send)
                    this.ToDepotDelivery(order, emp.Id);
              
                Edit(order);
                tran.Complete();
            }

        }
        /// <summary>
        /// 支付预付款
        /// </summary>
        /// <param name="order"></param>
        /// <param name="emp"></param>
        private void Pay(Order order, Employee emp = null)
        {
            FinanceBLL fbll = new FinanceBLL();
            var payMoney = fbll.PaymentOrder(order, emp);
            var payDeli = fbll.PaymentOrderDelivery(order, emp);
            order.Prepayments += payMoney;
            order.PaidDelivery += payDeli;
            Edit(order);
        }

        /// <summary>
        /// 支付差额
        /// </summary>
        /// <param name="orderDto"></param>
        /// <param name="emp"></param>
        public bool PayAdvanCharge(Guid orderId)
        {
            var order = Details(orderId);
            FinanceBLL financeBll = new FinanceBLL();
            using (var tran = new TransactionScope())
            {
                Pay(order); //扣款
                //是否信誉客户
                if (order.Prepayments >= order.Total * payments || order.Customer.CreditGrade())
                {
                    order.ProcessState = ProcessState.Checked;
                    SetOrderChangeRecord(order, DiscountType.StateChange, null);
                    if (order.IsSettlement)
                    {
                        if (order.DeliveryPriceTotal > order.PaidDelivery)
                        {
                            order.PaidDelivery += financeBll.PaymentOrderDelivery(order);
                        }
                        this.Edit(order);
                    }
                    else
                    {
                        //通知驻场接单
                        SendDockingOrder(order);
                    }
                }
                else
                {
                    return false;
                }
                this.Edit(order);
                tran.Complete();
            }
            return true;
        }


        /// <summary>
        /// 根据关键字和状态查计划单
        /// </summary>
        /// <param name="searchKey">模糊查询</param>
        /// <param name="state">状态</param>
        /// <param name="qinfo">翻页属性</param>
        /// <returns></returns>
        public KeyValuePair<int, IEnumerable<Order>> Select(string searchKey, OrderState? state, QueryInfo qinfo)
        {
            return Select(searchKey, state, null,null,null,qinfo.Page, qinfo.Rows);

        }
        /// <summary>
        /// 根据关键字和状态查计划单
        /// </summary>
        /// <param name="searchKey">模糊查询</param>
        /// <param name="state">状态</param>
        /// <param name="page">页码</param>
        /// <param name="rows">每页数量</param>
        /// <returns></returns>
        public KeyValuePair<int, IEnumerable<Order>> Select(string searchKey, OrderState? state, Guid? customerId = null, DateTime? startTime=null, DateTime? endTime=null, int page = 1, int rows = 10)
        {
            var query = Rep.Entities;
            if (!string.IsNullOrWhiteSpace(searchKey))
            {
                query = query.Where(p => p.Customer.Name.Contains(searchKey) || p.Customer.ShortName.Contains(searchKey)
                    || p.Account.Name.Contains(searchKey) || p.Creater.Name.Contains(searchKey) || p.Provider.Name.Contains(searchKey));
            }
            if (startTime!=null)
            {
                query = query.Where(p=>p.CreateTime>=startTime);
            }
            if (endTime != null)
            {
                query = query.Where(p => p.CreateTime <= endTime);
            }
            query = query.WhereIf(p => p.Customer.Id == customerId, customerId != null);
            if (state != null)
            {
                //结算
                if (state.Value.ToString() == "4")
                    query = query.Where(p => p.IsSettlement == true);
                else
                    query = query.Where(p => p.State == state);
            }
            var count = query.Count();
            var list = query.OrderByDescending(p => p.CreateTime).Paging(page, rows).ToList();
            return new KeyValuePair<int, IEnumerable<Order>>(count, list);
        }

        /// <summary>
        /// 应收账款
        /// </summary>
        /// <returns></returns>
        public object[][] Receivable()
        {
            var query =
                Rep.Entities.Where(
                    p => p.IsSettlement && (p.Total > p.Prepayments || p.DeliveryPriceTotal > p.PaidDelivery)).ToArray();
            var nowTime = DateTime.Now;
            var data =
                query.Select(
                    p =>
                        new
                        {
                            a = p.Account,
                            t = (p.Total - p.Prepayments),
                            d = p.DeliveryPriceTotal - p.PaidDelivery,
                            day = nowTime.Subtract(p.SettlementTime.Value).Days
                        }).ToArray();
            var list =
                data.GroupBy(p => new { p.a, p.day })
                    .Select(p => new object[] { p.Key.a, p.Key.day, p.Sum(x => x.t), p.Sum(x => x.d) })
                    .ToArray();
            return list;

        }

        public KeyValuePair<int, Order[]> GetFieldManOrder(Guid empId, int page, int rows, OrderState? state, OrderType? type, string name = null)
        {
            var q = Rep.Entities.Where(p => ((p.Provider.MainFieldMan.Id == empId && p.Provider.ProviderType != ProviderType.Depot)
                || (p.Provider.OperationsMan.Id == empId && p.Provider.ProviderType == ProviderType.Depot)) && p.ProcessState == ProcessState.Checked);
            q = q.WhereIf(p => p.State == state, state != null);
            q = q.WhereIf(p => p.OrderType == type, type != null);
            q = q.WhereIf(p => p.Provider.Name.Contains(name) || p.Customer.Name.Contains(name) || p.Customer.ShortName.Contains(name), name != null);
            var count = q.Count();
            q = q.OrderByDescending(p => p.CreateTime).Paging(page, rows);
            return new KeyValuePair<int, Order[]>(count, q.ToArray());
        }

        public KeyValuePair<int, Order[]> GetDirectorOrder(Guid empId, int page, int rows, OrderState? state, OrderType? type, DateTime? createtime, string name = null)
        {

            var q = Rep.Entities.Where(p => p.Creater.Department.ManagerId == empId && p.ProcessState == ProcessState.Checked);
            q = q.WhereIf(p => p.State == state, state != null);
            q = q.WhereIf(p => p.OrderType == type, type != null);
            q = q.WhereIf(p => p.Provider.Name.Contains(name) || p.Customer.Name.Contains(name) || p.Customer.ShortName.Contains(name), name != null);

            if (createtime != null)
            {
                var day = createtime.Value;
                var addDay = day.AddDays(1);
                q = q.Where(p => p.CreateTime >= day && p.CreateTime < addDay);
            }
            var count = q.Count();
            q = q.OrderByDescending(p => p.CreateTime).Paging(page, rows);
            return new KeyValuePair<int, Order[]>(count, q.ToArray());
        }

        /// <summary>
        /// 根据类型查询订单
        /// </summary>
        /// <param name="keys"></param>
        /// <param name="state"></param>
        /// <param name="page"></param>
        /// <param name="rows"></param>
        /// <returns></returns>
        public Tuple<int, Order[]> OrderList(string keys = null, Guid? empId = null, OrderType? orderType = null, OrderState? state = null, DateTime? startTime = null, DateTime? endTime = null, int page = 1, int rows = 10)
        {
            var q = Rep.Entities;//||p.OrderType==OrderType.Freedom||p.LockPriceState==LockPriceState.ToOrder
            if (empId != null)
            {
                q = q.Where(p => p.Creater.Id == empId);
            }
            if (orderType != null)
            {
                q = q.Where(p => p.OrderType == orderType);
            }
            if (state != null)
            {
                q = q.Where(p => p.State == state.Value);
            }
            else
            {
                q = q.Where(p => p.State != OrderState.Cancel);
            }
            if (!string.IsNullOrWhiteSpace(keys))
            {
                q = q.Where(p => p.Customer.Name.Contains(keys) || p.Customer.ShortName.Contains(keys));
            }
            var count = q.Count();
            var list = CollectionsExt.Paging(q.OrderByDescending(p => p.CreateTime), page, rows).ToArray();
            return Tuple.Create(count, list);
        }

        /// <summary>
        /// 应收账款报表查询
        /// </summary>
        /// <param name="createTime"></param>
        /// <param name="page"></param>
        /// <param name="rows"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public string[][] GetDebtReportArray(DateTime? settlementTime, int page, int rows, out int count)
        {
            //var query = Rep.Entities.Where(p => p.IsSettlement);
            var query = Rep.Entities;

            if (settlementTime != null)
            {
                var day = settlementTime.Value;
                var addDay = day.AddDays(1);
                query = query.Where(p => p.SettlementTime >= day && p.SettlementTime < addDay);
            }

            count = query.Count();

            query = CollectionsExt.Paging(query.OrderBy(p => p.SettlementTime), page, rows);

            var result = query
                .GroupBy(x => new { x.Customer, x.Creater, x.SettlementTime })
                .Select(g => new
            {
                DepartName = g.Key.Creater.Department.Name,
                CreateName = g.Key.Creater.Name,
                CustomName = g.Key.Customer.Name,
                Debt = g.Sum(x => x.Total + x.DeliveryPriceTotal - x.Prepayments - x.PaidDelivery),
                SettlementTime = g.Key.SettlementTime
            }).ToArray();

            int i = 1;
            var list = result.Select(p => new string[]
            {      
               i++.ToString(),
               p.DepartName, p.CreateName, p.CustomName, p.Debt.ToString("F2"),
               p.Debt > 0&&p.SettlementTime!=null?(DateTime.Now - p.SettlementTime.Value).Days.ToString():"",
            }).ToArray();

            return list;
        }


        /// <summary>
        /// 订单总量
        /// </summary>
        /// <returns></returns>
        public string[][] SelectVolumeTotal(DateTime begin, DateTime end)
        {
            var q = Rep.Entities.Where(p => p.CreateTime >= begin && p.CreateTime < end && p.State != OrderState.Pending);
            var array = q.GroupBy(p => new { p.CreateTime.Year, p.CreateTime.Month, p.CreateTime.Day }, p => p)
                    .Select(p => new { p.Key, b = p.Sum(x => x.Weight) })
                    .ToArray()
                    .Select(p => new[] { string.Join("-", p.Key.Year, p.Key.Month.ToString("00"), p.Key.Day.ToString("00")), p.b.ToString("0.00") }).OrderBy(p => p[0])
                    .ToArray();
            return array;
        }

        /// <summary>
        /// 日使用情况
        /// </summary>
        /// <param name="createTime"></param>
        /// <param name="page"></param>
        /// <param name="rows"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public string[][] GetDailyUsage(DateTime? createTime, string deptNames)
        {
            //var query = Rep.Entities.Where(p => p.IsSettlement);
            var query = Rep.Entities;

            if (createTime != null)
            {
                var day = createTime.Value;
                var addDay = day.AddDays(1);
                query = query.Where(p => p.CreateTime >= day && p.CreateTime < addDay);
            }
            if (!string.IsNullOrWhiteSpace(deptNames))
            {
                query = query.Where(p => p.Creater.Department.Name.Contains(deptNames));
            }

            var result = query
                .GroupBy(x => new { x.Creater.Department.Name, x.Creater })
                .Select(g => new
                {
                    DepartName = g.Key.Name,
                    CreateName = g.Key.Creater.Name,
                    Pending = g.Where(p => p.State == OrderState.Pending).Sum(x => 1),
                    Checked = g.Where(p => p.State == OrderState.Checked).Sum(x => 1),
                    Ordered = g.Where(p => p.State == OrderState.Ordered).Sum(x => 1),
                    Send = g.Where(p => p.State == OrderState.Send).Sum(x => 1),
                    Confirmed = g.Where(p => p.State == OrderState.Confirmed).Sum(x => 1),
                    Settlement = g.Where(p => p.State == OrderState.Settlement).Sum(x => 1),
                    End = g.Where(p => p.State == OrderState.End).Sum(x => 1),
                    Cancel = g.Where(p => p.State == OrderState.Cancel).Sum(x => 1),
                    Return = g.Where(p => p.State == OrderState.Return).Sum(x => 1),
                    Refund = g.Where(p => p.State == OrderState.Refund).Sum(x => 1)
                }).ToArray();

            int i = 1;
            var list = result.Select(p => new string[]
            { 
               p.DepartName, p.CreateName,p.Pending.ToString(),p.Checked.ToString(),p.Ordered.ToString()
               ,p.Send.ToString(),p.Confirmed.ToString(),p.Settlement.ToString(),p.End.ToString(),p.Cancel.ToString(),p.Return.ToString()
               ,p.Refund.ToString()
            }).ToArray();

            return list;
        }
    }
}
